import {parseHTML} from './parse'
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g
function genProps(attrs) {
  if (!attrs.length) return undefined
  let props = {}
  attrs.forEach((attr) => {
    if (attr.name === 'style') {
      let style = {}
      attr.value.replace(/\s*([^\s;:]+)\s*:\s*([^\s;:]+)\s*/g, function () {
        style[arguments[1]] = arguments[2]
      })
      attr.value = style
    }
    props[attr.name] = attr.value
  })
  return JSON.stringify(props)
}
function genText(child) {
  const tagRE = defaultTagRE
  let text = child.text.trim()
  if(!text) return
  if ( !tagRE.test(child.text)) return `_v("${child.text}")`
  let tokens = []
  let lastIndex = (tagRE.lastIndex = 0)
  let match, index, tokenValue
  while ((match = tagRE.exec(text))) {
    index = match.index
    tokenValue = text.slice(lastIndex, index)
    if (index > lastIndex) {
      tokens.push(JSON.stringify(tokenValue))
    }
      tokens.push(`_s(${match[1].trim()})`)
    lastIndex = index + match[0].length
    if (lastIndex < text.length) {
      tokens.push(JSON.stringify(text.slice(lastIndex)))
    }
  }
  return `_v(${tokens.join('+')})`
}
function genChildren(children) {
  if (!children.length) return undefined
  children = children.filter(child => !(child.type === 2 && !child.text.trim()))
  return (
    '[' +
    children
      .map((child) => {
        switch (child.type) {
          case 1:
            return generate(child)
          case 2:
            return genText(child)
          default:
            break
        }
      })
      .join(',') +
    ']'
  )
}
function generate(ast) {
  return `_c('${ast.tag}',${genProps(ast.attrs)},${genChildren(ast.children)})`
}
export function compileToFunction(template) {
  const ast = parseHTML(template)
  const code = generate(ast)
  return new Function(`with(this){return ${code}}`)

}
